package org.jaronsource.framework.core;

import java.io.File;
import java.io.IOException;
import java.io.Serializable;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.util.LinkedList;
import java.util.List;

import org.apache.commons.io.FileExistsException;
import org.apache.commons.io.FileUtils;
import org.jaronsource.framework.util.DateUtils;


public class AttachmentUtils {
	
	public static final String BASE_URL_PREFIX = "/attachments";
	
	public static final String TEMP_NAMESPACE = "temp";
	
	/**
	 * 清空临时文件目录
	 * @throws IOException
	 */
	public static void cleanTempDir() throws IOException{
		File tempDir = getUploadBaseDir(TEMP_NAMESPACE);
		FileUtils.deleteDirectory(tempDir);
	}
	/**
	 * 获取临时文件目录
	 * @return
	 */
	public static File getTempBaseDir(){
		File tempDir = getUploadBaseDir(TEMP_NAMESPACE);
		return tempDir;
	}
	/**
	 * 获取临时文件目录()
	 * @param prefix	用于防止冲突,使用getTempBaseDir()/prefix作为目标目录
	 * @return
	 */
	public static File getTempBaseDir(String prefix){
		File tempDir = getUploadBaseDir(TEMP_NAMESPACE);
		if(prefix != null){
			tempDir = new File(tempDir, prefix);
			if(!tempDir.exists()){
				tempDir.mkdirs();
			}
		}
		return tempDir;
	}
	
	/**
	 * 将临时文件移至指定目录
	 * @param tempNo
	 * @param targetNamespace
	 * @param targetRecordId
	 */
	public static void moveTempFile(Integer tempNo, String targetNamespace, Integer targetRecordId){
		File tmpBaseDir = getTempBaseDir();
		moveFiles(tmpBaseDir, tempNo, targetNamespace, targetRecordId);
	}
	/**
	 * 将临时文件移至指定目录
	 * @param prefix
	 * @param tempNo
	 * @param targetNamespace
	 * @param targetRecordId
	 */
	public static void moveTempFile(String prefix, Integer tempNo, String targetNamespace, Integer targetRecordId){
		File tmpBaseDir = getTempBaseDir(prefix);
		moveFiles(tmpBaseDir, tempNo, targetNamespace, targetRecordId);
	}
	/**
	 * 将目录文件移至指定位置
	 * @param baseDir
	 * @param recordId
	 * @param targetNamespace
	 * @param targetRecordId
	 */
	public static void moveFiles(File baseDir, Integer recordId, String targetNamespace, Integer targetRecordId){
		File sourceDir = getUploadDir(baseDir, recordId);
		moveFiles(sourceDir, targetNamespace, targetRecordId);
	}
	/**
	 * 将目录文件移至指定位置
	 * @param sourceDir	文件所在文件夹
	 * @param targetNamespace
	 * @param targetRecordId
	 */
	public static void moveFiles(File sourceDir, String targetNamespace, Integer targetRecordId){
		if(sourceDir == null || sourceDir.isFile()){
			return;
		}
		File[] tmpFiles = sourceDir.listFiles();
		if(tmpFiles != null && tmpFiles.length > 0){
			File targetBaseDir = getUploadBaseDir(targetNamespace);
			File targetDir = getUploadDir(targetBaseDir, targetRecordId);
			for(int i = 0, len = tmpFiles.length; i < len; i++){
				File tmpFile = tmpFiles[i];
				try {
					FileUtils.moveFileToDirectory(tmpFile, targetDir, true);
				}catch(FileExistsException fee){
					fee.printStackTrace();
				}catch(IOException e) {
					e.printStackTrace();
				}
			}
		}
	}
	
	/**
	 * 获取对象附件根目录
	 * @param clazz	对象类
	 * @return
	 */
	public static File getUploadBaseDir(Class<?> clazz){
		String namespace = clazz.getSimpleName();
		return getUploadBaseDir(namespace);
	}
	/**
	 * 获取对象附件根目录
	 * @param namespace	目录前缀(通常为对象的类名)
	 * @return
	 */
	public static File getUploadBaseDir(String namespace){
		String realPath = AppContext.getInstance().getServletContext().getRealPath(BASE_URL_PREFIX);
		File baseDir = new File(realPath, namespace);
		if(!baseDir.exists()){
			baseDir.mkdirs();
		}
		return baseDir;
	}
	/**
	 * 获取上传路径
	 * @return
	 */
	public static String getRootRealPath(){
		String realPath = AppContext.getInstance().getServletContext().getRealPath(BASE_URL_PREFIX);
		return realPath;
	}
	
	/**
	 * 获取上传路径
	 * @return
	 */
	public static File getRootRealPathFile(){
		File dir = new File(getRootRealPath());
		return dir;
	}
	
	/**
	 * 获取附件上传路径
	 * @param source	对象附件根目录
	 * @param recordId	对象主键ID
	 * @return
	 */
	public static File getUploadDir(File baseDir, Integer recordId){
		if(baseDir == null || baseDir.isFile()){
			return null;
		}
		NumberFormat format = new DecimalFormat("000,000,000");
		String str = format.format(recordId).replaceAll(",", "/");
		File dir = new File(baseDir, str);
		if(!dir.exists())
			dir.mkdirs();
		return dir;
	}
	
	/**
	 * 下载地址根目录(WEB地址)
	 * @param namespace
	 * @param recordId
	 * @return
	 */
	public static String getDownloadBasePath(String namespace, Integer recordId){
		NumberFormat format = new DecimalFormat("000,000,000");
		String str = format.format(recordId).replaceAll(",", "/");
		StringBuilder path = new StringBuilder(AppContext.getInstance().getServletContext().getContextPath());
		path.append(BASE_URL_PREFIX).append('/').append(str);
		return path.toString();
	}
	/**
	 * 下载地址
	 * @param namespace
	 * @param recordId
	 * @return
	 */
	public static String getDownloadPath(String namespace, Integer recordId, String fileName){
		NumberFormat format = new DecimalFormat("000,000,000");
		String str = format.format(recordId).replaceAll(",", "/");
		StringBuilder path = new StringBuilder(AppContext.getInstance().getServletContext().getContextPath());
		path.append(BASE_URL_PREFIX).append('/').append(namespace).append('/').append(str).append('/').append(fileName);
		return path.toString();
	}
	/**
	 * 获取附件文件
	 * @param source	对象附件根目录
	 * @param recordId	对象主键ID
	 * @param fileName	附件名
	 * @return
	 */
	public static File getUploadFile(File baseDir, Integer recordId, String fileName){
		File dir = getUploadDir(baseDir, recordId);
		File file = new File(dir, fileName);
		return file;
	}
	
	/**
	 * 获取附件列表
	 * @param source	对象附件根目录
	 * @param recordId	对象主键ID
	 * @return
	 */
	public static String[] getUploadFileNames(File baseDir, Integer recordId){
		File dir = getUploadDir(baseDir, recordId);
		return dir.list();
	}
	
	/**
	 * 获取附件文件列表
	 * @param source	对象附件根目录
	 * @param recordId	对象主键ID
	 * @return
	 */
	public static File[] getUploadFiles(File baseDir, Integer recordId){
		File dir = getUploadDir(baseDir, recordId);
		return dir.listFiles();
	}
	
	public static final long KB = 1024L, MB = KB*1024L, GB = MB * 1024L;
	public static final String DESC_BYTE = "BYTE", DESC_KB = "KB", DESC_MB = "MB", DESC_GB = "GB";
	
	public static String getFileSize(long size){
		NumberFormat format = new DecimalFormat("0.##");
		if(size < KB){
			return size + DESC_BYTE;
		}else if(size < MB){
			return format.format(size * 1.0/ KB) + DESC_KB;
		}else if(size < GB){
			return format.format(size * 1.0/ MB) + DESC_MB;
		}else{
			return format.format(size * 1.0 / GB) + DESC_GB;
		}
	}
	
	/**
	 * 获取附件详细
	 * @param baseDir
	 * @param recordId
	 * @param fileName
	 * @return
	 */
	public static WebAttachment getUploadWebAttachment(File baseDir, Integer recordId, String fileName){
		File dir = getUploadDir(baseDir, recordId);
		File file = new File(dir, fileName);
		getUploadBaseDir("");
		String namespace = "";
		String path = getRootRealPath(), baseFilePath = baseDir.getAbsolutePath();
		namespace = baseFilePath.substring(baseFilePath.indexOf(path, 0) + path.length()).replaceAll("\\\\", "/");
		if(namespace.startsWith("/")){
			namespace = namespace.substring(1);
		}
		String webPath = getDownloadPath(namespace, recordId, fileName);
		long fileLength = file.length();
		String fileSize = getFileSize(fileLength), realPath = file.getAbsolutePath();
		String createTime = DateUtils.currentDateTime();
		WebAttachment attachment = new WebAttachment(webPath, realPath, fileName, fileSize, fileLength, createTime);
		return attachment;
	}
	
	/**
	 * 获取附件详情列表
	 * @param baseDir
	 * @param recordId
	 * @return
	 */
	public static List<WebAttachment> getUploadWebAttachments(Class<?> clazz, Integer recordId){
		File baseDir = getUploadBaseDir(clazz);
		return getUploadWebAttachments(baseDir, recordId);
	}
	
	/**
	 * 获取附件详情列表
	 * @param baseDir
	 * @param recordId
	 * @return
	 */
	public static List<WebAttachment> getUploadWebAttachments(File baseDir, Integer recordId){
		List<WebAttachment> result = new LinkedList<AttachmentUtils.WebAttachment>();
		File dir = getUploadDir(baseDir, recordId);
		File[] files = dir.listFiles();
		
		if(files != null){
			for(File file : files){
				if(file.isDirectory())
					continue;
				WebAttachment attachment = getUploadWebAttachment(baseDir, recordId, file.getName());
				result.add(attachment);
			}
		}
		return result;
	}
	/**
	 * 删除附件
	 * @param source	对象附件根目录
	 * @param recordId	对象主键ID
	 * @param fileName	附件名称
	 * @return
	 */
	public static boolean deleteUploadFile(File baseDir, Integer recordId, String fileName){
		File dir = getUploadDir(baseDir, recordId);
		File file = new File(dir, fileName);
		if(file.exists())
			return file.delete();
		else
			return true;
	}
	/**
	 * 是否存在附件
	 * @param source	对象附件根目录
	 * @param recordId	对象主键ID
	 * @param fileName	附件名称
	 * @return
	 */
	public static boolean existsUploadFile(File baseDir, Integer recordId, String fileName){
		File dir = getUploadDir(baseDir, recordId);
		File file = new File(dir, fileName);
		return file.exists();
	}
	
	/**
	 * 删除所有附件
	 * @param source	对象附件根目录
	 * @param recordId	对象主键ID
	 * @return
	 */
	public static void clearUploadDir(File baseDir, Integer recordId){
		File dir = getUploadDir(baseDir, recordId);
		try {
			FileUtils.cleanDirectory(dir);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	public static void main(String[] args) {
		/*File baseDir = new File("E:/uploadify");
		File dir = getUploadDir(baseDir, 1019);
		System.out.println(dir.getAbsolutePath());
		System.out.println(getUploadFileNames(baseDir, 1019));*/
		
		File file = new File("D:/a/b/c/", "/");
		System.out.println(file.getAbsolutePath());
		System.out.println(file.getName());
	}

	public static class WebAttachment implements Serializable {
		/**
		 * 
		 */
		private static final long serialVersionUID = -4171520823228432268L;
		private String webPath;
		private String realPath;
		private String fileName;
		private String fileSize;
		private long fileLength = 0l;
		private String createTime;

		public WebAttachment() {
		}

		public WebAttachment(String webPath, String realPath, String fileName,
				String fileSize, long fileLength, String createTime) {
			super();
			this.webPath = webPath;
			this.realPath = realPath;
			this.fileName = fileName;
			this.fileSize = fileSize;
			this.fileLength = fileLength;
			this.createTime = createTime;
		}

		public String getWebPath() {
			return webPath;
		}

		public void setWebPath(String webPath) {
			this.webPath = webPath;
		}

		public String getFileName() {
			return fileName;
		}

		public void setFileName(String fileName) {
			this.fileName = fileName;
		}

		public String getFileSize() {
			return fileSize;
		}

		public void setFileSize(String fileSize) {
			this.fileSize = fileSize;
		}

		public long getFileLength() {
			return fileLength;
		}

		public void setFileLength(long fileLength) {
			this.fileLength = fileLength;
		}

		public String getCreateTime() {
			return createTime;
		}

		public void setCreateTime(String createTime) {
			this.createTime = createTime;
		}

		public String getRealPath() {
			return realPath;
		}

		public void setRealPath(String realPath) {
			this.realPath = realPath;
		}

	}
}
